package com.clusterswisdom.horn.api.tmall.config;

import java.io.InputStream;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import javax.servlet.ServletContext;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.clusterswisdom.horn.api.ioc.HornAction;
import com.clusterswisdom.horn.api.ioc.api.HornConfig;
import com.clusterswisdom.horn.api.ioc.struct.StructConfig;
import com.clusterswisdom.horn.api.ioc.struct.StructContainer;

public class TmallConfig {
	
	private String channel;
	
	private Map<String, TmallApplication> applicationMap = new HashMap<String, TmallApplication>();
	
	private Logger log = LoggerFactory.getLogger(TmallConfig.class);
	
	@SuppressWarnings("unchecked")
	public TmallConfig(ServletContext sc) {
		InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(getConfigName());
		 try {
			Document document = new SAXReader().read(is);
			Element element = document.getRootElement();
			channel = element.elementTextTrim("channel");
			
			loadDefaultAction(element.element("defaultAction"));
			loadApplication(element.elementIterator("application"));
			loadService(element.element("services"));
			loadStructs(element.element("strcuts"));
			
		} catch (DocumentException e) {
			e.printStackTrace();
			
		}
	}
	
	public Map<String, TmallApplication> getTmallApplications() {
		return applicationMap;
	}

	public String getChannel() {
		return channel;
	}
	
	public TmallApplication getApplication(String name) {
		if (name == null) {
			return getDefaultApplication();
		}
		
		return applicationMap.get(name);
	}
	
	public TmallApplication getDefaultApplication() {
		for (TmallApplication application : applicationMap.values()) {
			if (application.isDefaultApplication()) {
				return application;
			}
		}
		
		return null;
	}
	
	private void loadApplication(Iterator<Element> applicationElements) {
		while (applicationElements.hasNext()) {
			Element applicationElement = applicationElements.next();
			TmallApplication applicationConfig = new TmallApplication(applicationElement);
			applicationMap.put(applicationConfig.getName(), applicationConfig);
		}
	}
	
	private void loadDefaultAction(Element defaultActionElement) {
		if (defaultActionElement == null) {
			return;
		}
		
		String classValue = defaultActionElement.attributeValue("class").trim();
		if (classValue == null || classValue.trim().length() == 0) {
			return;
		}
		
		try {
			HornAction defaultAction = (HornAction) Thread.currentThread().getContextClassLoader().loadClass(classValue).newInstance();
			HornConfig.getConfig().addChannelAciton(channel, defaultAction);
			
		} catch (Exception e) {
			e.printStackTrace();
			
		}
	}
	
	@SuppressWarnings("unchecked")
	private void loadService(Element servicesElement) throws DocumentException {
		Iterator<Element> serviceIterator = servicesElement.elementIterator("service");
		while (serviceIterator.hasNext()) {
			Element serviceElement = serviceIterator.next();
			String url = serviceElement.attributeValue("url");
			
			log.debug("add chanell '" + channel + " servce " + url);
			HornConfig.getConfig().addServiceConfig(channel, Thread.currentThread().getContextClassLoader().getResourceAsStream(url));
		}
	}
	
	@SuppressWarnings("unchecked")
	private void loadStructs(Element structsElement) throws DocumentException {
		Iterator<Element> structFileIterator = structsElement.elementIterator("struct");
		while (structFileIterator.hasNext()) {
			String structUrl = structFileIterator.next().attributeValue("url");
			log.debug("load struct :" + structUrl);
			
			InputStream structIs = Thread.currentThread().getContextClassLoader().getResourceAsStream(structUrl);
			Element structRootElement = new SAXReader().read(structIs).getRootElement();
			Iterator<Element> structIterator = structRootElement.elementIterator("struct");
			while (structIterator.hasNext()) {
				Element structItem = structIterator.next();
				StructContainer.getContainer().addStruct(new StructConfig(structItem));
			}
		}
		
	}
	
	private String getConfigName() {
		if (HornConfig.getConfig().isRuntime()) {
			return "tmall/tmall.xml";
			
		} else {
			return "tmall/tmall_" + HornConfig.getConfig().getScope() + ".xml";
			
		}
	}
}